package com.moli.iov.down.command.design.command.retry.impl;

import com.moli.iov.down.constants.Constant;
import com.moli.iov.down.enums.ResResultEnum;
import com.moli.iov.down.enums.ResultEnum;
import com.moli.iov.down.enums.command.upgrade.UpgradeStatusEnum;
import com.moli.iov.down.model.dto.remoting.CommandDto;
import com.moli.iov.down.model.po.VehicleCommand;
import com.moli.iov.down.command.codec.encode.ProtocolEncoder;
import com.moli.iov.down.command.codec.encode.data.DataEncoder;
import com.moli.iov.down.command.design.command.retry.RetryCommand;
import com.moli.iov.down.command.design.factory.DataEncoderFactory;
import com.moli.iov.down.command.mq.SendCache;
import com.moli.iov.down.command.mq.SendHandle;
import com.moli.iov.down.service.IVehicleCommandService;
import com.moli.iov.util.ByteArrayUtil;
import com.moli.iov.util.SpringContextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>
 *  升级指令处理 重试机制
 * </p>
 *
 * @author: zql
 * @Date: 2019/1/9 14:35
 */
public class UpgradeCommand implements RetryCommand {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    private SendCache sendCache = SpringContextUtils.getBean("sendCache");
    private IVehicleCommandService vehicleCommandService =
            SpringContextUtils.getBean("vehicleCommandService");
    private SendHandle sendHandle = SpringContextUtils.getBean("sendHandle");

    @Override
    public void handle(CommandDto commandDto) {
        CommandDto commandDtoCache = sendCache.getCacheSendCommand(commandDto);
        logger.info("[补发] [升级命令] 缓存结果：{}, 入参：{} ", commandDtoCache, commandDto);

        if(commandDtoCache == null){
            logger.error("[补发] [升级命令] 取消 原因：[缓存commandDtoCache 为空或补发超时] vin：{}  参数：{}",
                    commandDto.getVin(), commandDto);
            return;
        }

        if(commandDtoCache.getUpgradeStatus() != null &&
                UpgradeStatusEnum.UPADATE_SUCCESSED.getFlag() == commandDtoCache.getUpgradeStatus()){
            logger.error("[补发] [升级命令] 取消 原因：[终端已响应成功] vin：{}  参数：{}",
                    commandDto.getVin(), commandDto);
            return;
        }

        if(commandDtoCache.getSendingTimes() != null &&
                Constant.UPGRADE_INTERVAL_TIMES >= commandDtoCache.getSendingTimes()){
            logger.error("[补发] [升级命令] 取消 原因：[已达到最大补发次数 {}次]  vin：{},    参数：{}",
                    commandDtoCache.getSendingTimes(), commandDto.getVin(), commandDto);

            //置为失败：更新数据库、缓存
            commandDtoCache.setResult(ResResultEnum.ERROR.getFlag());
            commandDtoCache.setSendingTimes(commandDto.getSendingTimes());
            sendCache.updateResResult(commandDto, commandDtoCache);

            upgradeHandle(commandDtoCache);
            return;
        }

        retrySend(commandDto);
    }

    /**
     * 补发升级命令
     * @param commandDto
     */
    public void retrySend(CommandDto commandDto){
        DataEncoder dataEncoder = DataEncoderFactory.getDataEncoder(commandDto.getCommand());
        if(dataEncoder == null){
            logger.error("[补发]，[升级命令] 失败，未定义命令协议, 命令协议：{}, 参数：{}",
                    commandDto.getCommand(), commandDto);
            return;
        }
        byte[] data = dataEncoder.encode(commandDto);

        ProtocolEncoder protocolEncoder = new ProtocolEncoder(commandDto.getCommand(),
                ByteArrayUtil.strToAscii(commandDto.getVin()), data);
        byte[] allData = protocolEncoder.endcode();

        sendHandle.retrySend(commandDto, allData);
    }

    /**
     * 更新数据库
     * @param commandDtoCache
     */
    public void upgradeHandle(CommandDto commandDtoCache){
        try{

            int operatorResult = ResultEnum.SUCCESS.getFlag();
            String failMsg = "";
            if(commandDtoCache.getUpgradeStatus() == null ||
                    UpgradeStatusEnum.UPADATE_SUCCESSED.getFlag() != commandDtoCache.getUpgradeStatus()){

                operatorResult = ResultEnum.FAIL.getFlag();

                failMsg = commandDtoCache.getUpgradeStatus() != null ?
                            UpgradeStatusEnum.getMsg(commandDtoCache.getUpgradeStatus()) :
                            ResResultEnum.ERROR.getMsg();
            }

            VehicleCommand vehicleCommand = new VehicleCommand();
            vehicleCommand.setVin(commandDtoCache.getVin());
            vehicleCommand.setResponseNo(commandDtoCache.getCommandNo());
            vehicleCommand.setResult(operatorResult);
            vehicleCommand.setResultMemo(failMsg);

            vehicleCommandService.updateResult(vehicleCommand);
        }catch(Exception e){
            logger.error("[补发] [恒领远程升级命令] 更新数据库 异常", e);
        }
    }
}
